package com.intercom.fdfr;

import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.PreviewCallback;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.widget.Toast;


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * Created by Dushyant on 2/2/2017.
 */

@SuppressWarnings("deprecation")
public class CameraController implements ErrorCallback, PreviewCallback {
    boolean flag = false;

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        lastPreviewFrameTime = System.currentTimeMillis();
        camera.addCallbackBuffer(cameraPreviewBuffer);
    }

    private Camera camera = null;
    //static int frontCam = 0;
    private SurfaceHolder surfaceHolder;
    private Context context;
    private byte[] cameraPreviewBuffer;
    public boolean enroll;
    String firstName = "";
    String lastName = "";

    //创芯视讯双目摄像头(型号为001-0511-V1.0)：camIdx=0是彩色，camIdx=1是红外
    //安装方向为usb线在下方
    //双目摄像头，彩色sensor摄像机控制选项里面的滚动值为3，2018-10-18修改，滚动值为1时图像左右是相反的
    //双目摄像头，彩色sensor要旋转270度
    private int cameraOrientation = 270;//90//270

    private final String TAG = "CameraController";

    private Handler mainHandler;
    private boolean startPreview = false;
    private long lastPreviewFrameTime;//判断摄像头是否断开


    public interface CameraControllerListener {
        void onDraw(int faceArray[], int color);

        void onError(int error);
    }


    private CameraControllerListener listener = null;


    public void setListener(CameraControllerListener listener) {
        this.listener = listener;
    }


    CameraDetectView cameraDetectView;


    public CameraController(Context context, boolean enroll, String firstName, String lastName, CameraDetectView cameraDetectView) {
        this.cameraDetectView = cameraDetectView;
        this.context = context;
        this.enroll = enroll;
        this.firstName = firstName;
        this.lastName = lastName;


        mainHandler = new Handler(context.getMainLooper());

        mainHandler.postDelayed(runnableClick, 1000);//定时检测摄像头是否已断开
    }

    private Runnable runnableClick = new Runnable() {
        @Override
        public void run() {
            mainHandler.postDelayed(this, 1000);
            if (startPreview == true) {
                long currentTime = System.currentTimeMillis();
                if ((currentTime - lastPreviewFrameTime) > 5000) {
                    Log.e(TAG, "runnableClick run: the camera disconnect !!!!!!");
                    if (listener != null)
                        listener.onError(-1);
                }
            }
        }
    };

    public static boolean hasCamera(Context context) {
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    public static int getNumberOfCameras(Context context) {
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        return Camera.getNumberOfCameras();
    }


    public Camera openFrontFacingCameraGingerbread() {
        Log.i(TAG, "openFrontFacingCameraGingerbread: threadId " + Thread.currentThread().getId());

        int cameraCount = 0;
        //cameraFace = Camera.CameraInfo.CAMERA_FACING_BACK;

        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras();
        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {

            Log.e(TAG, "cameraId " + camIdx);

            Camera.getCameraInfo(camIdx, cameraInfo);
            //创芯视讯双目摄像头(型号为001-0511-V1.0)：camIdx=0是红外，camIdx=1是彩色
            if (camIdx == 0) {//不打开红外
                continue;
            }

            try {
                if (camera != null) {
                    camera.release();
                }
                camera = Camera.open(camIdx);
                //frontCam = camIdx;
                System.out.println("Front Camera Opened");
            } catch (RuntimeException e) {
                Toast.makeText(context, "Camera failed to Open", Toast.LENGTH_LONG);
                Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
            }
        }

        /**
         * 分辨率
         */
       // Log.e(TAG, "cameraId " + frontCam);
        if (camera != null) {
            getCameraSupportedPreviewSizes();
            setOptimalPreviewSize(Constants.width, Constants.height);
        }

        return camera;
    }

    public void releaseCamera() {
        Log.i(TAG, "releaseCamera: ");
        try {
            /**
             * Release the camera
             */
            if (camera != null) {
                camera.release();
            }
            camera = null;
        } catch (Exception e) {
            Log.d("CameraController", "closeCamera: Exception while releasing camera->" + e.getMessage());
            e.printStackTrace();
        }
    }

    public void setPreviewDisplay(Object holder) {
        try {
            surfaceHolder = (SurfaceHolder) holder;
            System.out.println("Camera: " + camera);
            if (camera != null)
//                surfaceHolder.setFixedSize(1280, 720);
                camera.setPreviewDisplay(surfaceHolder);
        } catch (IOException e) {
            Log.d("CameraController", "setPreviewDisplay: Exception->" + e.getMessage());
        }
    }

    public void startPreview() {
        Log.i(TAG, "startPreview: ");
        try {
            startPreview = true;
            lastPreviewFrameTime = System.currentTimeMillis();

            if (camera != null) {
//            camera.setPreviewDisplay(surfaceHolder);
                cameraPreviewBuffer = new byte[(int) (getPreviewWidth() * getPreviewHeight() * 1.5)];//1.5 for yuv image
                camera.addCallbackBuffer(cameraPreviewBuffer);
                camera.setPreviewCallbackWithBuffer(this);
                camera.setErrorCallback(this);
                camera.startPreview();
            }
        } catch (Exception e) {
            Toast.makeText(context, "Exception in starting preview of Camera", Toast.LENGTH_LONG);
            Log.d("CameraController", "startPreview: Exception->" + e.getMessage());
            e.printStackTrace();
        }
    }

    public void stopPreview() {
        Log.i(TAG, "stopPreview: ");
        try {
            startPreview = false;

            if (camera != null) {
                camera.stopPreview();
                camera.setPreviewCallbackWithBuffer(null);
                camera.addCallbackBuffer(null);
                camera.setErrorCallback(null);
            }
        } catch (Exception e) {
            Log.d("CameraController", "stopPreview: Exception->" + e.getMessage());
            e.printStackTrace();
        }
    }

    private void getCameraSupportedPreviewSizes() {
        Camera.Parameters params = camera.getParameters();
        List<Camera.Size> sizes = params.getSupportedPreviewSizes();
        for (Camera.Size cs : sizes) {
            System.out.println("Optimal Sizes: W: " + cs.width + " H: " + cs.height);
        }
    }

    /**
     * 显示方向
     */
    void setOptimalPreviewSize(int height, int width) {

        Camera.Parameters params = camera.getParameters();
        params.setPreviewSize(width, height);
//        /**摄像头旋转270度   预览画面(帧数据)横屏变竖屏，宽高切换**/
//        if (cameraOrientation == 0) {
//            params.setPreviewSize(width, height);
//        } else {
//            params.setPreviewSize(height, width);
//        }
        params.setPictureSize(320, 240);
        camera.setParameters(params);
        camera.setDisplayOrientation(cameraOrientation);
        System.out.println("Width Get Size: " + params.getPreviewSize().width);
        Log.e("Width Get Size: ", "PreviewSize width: " + params.getPreviewSize().width + ", PreviewSize height: " + params.getPreviewSize().height);
    }


    @Override
    public void onError(int error, Camera camera) {
        Log.e(TAG, "onError: " + error);
        if (listener != null)
            listener.onError(error);
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    private byte[] PathToJpegBuffer(final String imagePath) {
        Bitmap scr = BitmapFactory.decodeFile(imagePath);
        //Bitmap rBmp = FileTool.rotaingImageView(0, scr);
        Bitmap rBmp = scr;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        rBmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] data1 = baos.toByteArray();
        return data1;
    }


    public int getPreviewWidth() {
        Camera.Parameters parameters = camera.getParameters();
        return parameters.getPreviewSize().width;
    }

    public int getPreviewHeight() {
        Camera.Parameters parameters = camera.getParameters();
        return parameters.getPreviewSize().height;
    }


    public static byte[] rotateYUV420DegreeCounter90(byte[] data, int imageHeight, int imageWidth) {
        byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
        int nWidth = 0, nHeight = 0;
        int wh = 0;
        int uvHeight = 0;
        if (imageWidth != nWidth || imageHeight != nHeight) {
            nWidth = imageWidth;
            nHeight = imageHeight;
            wh = imageWidth * imageHeight;
            uvHeight = imageHeight >> 1;// uvHeight = height / 2
        }
        // ??Y
        int k = 0;
        for (int i = 0; i < imageWidth; i++) {
            int nPos = 0;
            for (int j = 0; j < imageHeight; j++) {
                yuv[k] = data[nPos + i];
                k++;
                nPos += imageWidth;
            }
        }
        for (int i = 0; i < imageWidth; i += 2) {
            int nPos = wh;
            for (int j = 0; j < uvHeight; j++) {
                yuv[k] = data[nPos + i];
                yuv[k + 1] = data[nPos + i + 1];
                k += 2;
                nPos += imageWidth;
            }
        }
        return rotateYUV420Degree180(yuv, imageWidth, imageHeight);
    }

    /**
     * 摄像头旋转270度   预览画面(帧数据)横屏变竖屏，宽高切换
     **/
    public static byte[] rotateYUV420Degree90(byte[] data, int imageHeight, int imageWidth) {
        byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
        // Rotate the Y luma
        int i = 0;
        for (int x = 0; x < imageWidth; x++) {
            for (int y = imageHeight - 1; y >= 0; y--) {
                yuv[i] = data[y * imageWidth + x];
                i++;
            }
        }
//         Rotate the U and V color components
        i = imageWidth * imageHeight * 3 / 2 - 1;
        for (int x = imageWidth - 1; x > 0; x = x - 2) {
            for (int y = 0; y < imageHeight / 2; y++) {
                yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];
                i--;
                yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth)
                        + (x - 1)];
                i--;
            }
        }
        return yuv;
    }


    private static byte[] rotateYUV420Degree180(byte[] data, int imageHeight, int imageWidth) {
        byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
        int i = 0;
        int count = 0;
        for (i = imageWidth * imageHeight - 1; i >= 0; i--) {
            yuv[count] = data[i];
            count++;
        }
        i = imageWidth * imageHeight * 3 / 2 - 1;
        for (i = imageWidth * imageHeight * 3 / 2 - 1; i >= imageWidth
                * imageHeight; i -= 2) {
            yuv[count++] = data[i - 1];
            yuv[count++] = data[i];
        }
        return yuv;
    }

    private static byte[] rotateYUV420Degree270(byte[] data, int imageHeight, int imageWidth) {
        byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
        // Rotate the Y luma
        int i = 0;
        for (int x = imageWidth - 1; x >= 0; x--) {
            for (int y = 0; y < imageHeight; y++) {
                yuv[i] = data[y * imageWidth + x];
                i++;
            }
        }
        // Rotate the U and V color components  	i = imageWidth*imageHeight;
        for (int x = imageWidth - 1; x > 0; x = x - 2) {
            for (int y = 0; y < imageHeight / 2; y++) {
                yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x - 1)];
                i++;
                yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];
                i++;
            }
        }
        return yuv;
    }

}
